﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Security;
using Elmah;
using MVCms.Core.Entities;
using MVCms.Core.Services;

namespace MVCms.Core.Developers
{
    /// <summary>
    /// The base controller all plugin controller's MUST inherit from this controller
    /// </summary>
    [TidyHtml]
    [HandleError]
    public class BaseController : Controller
    {
        /// <summary>
        /// Gets or sets a value indicating whether the page is in edit mode.
        /// </summary>
        /// <value><c>true</c> if [edit mode]; otherwise, <c>false</c>.</value>
        public bool EditMode
        {
            get
            {
                return true;// (bool)Session["EditMode"];
            }
            set
            {
                Session["EditMode"] = value;
            }
        }
        /// <summary>
        /// Gets or sets the current page.
        /// </summary>
        /// <value>The current page.</value>
        public VirtualPage CurrentPage
        {
            get
            {

                return (VirtualPage)Session["__CurrentPage"];
            }
            set
            {
                Session["__CurrentPage"] = value;
            }
        }
        /// <summary>
        /// Gets or sets the referring page.
        /// </summary>
        /// <value>The referring page.</value>
        public VirtualPage ReferringPage
        {
            get
            {

                return (VirtualPage)Session["__ReferringPage"];
            }
            set
            {
                Session["__ReferringPage"] = value;
            }
        }
        /// <summary>
        /// Gets or sets the current PageModule (!! NOT YET IMPLEMENTED !!).
        /// </summary>
        /// <value>The current page module.</value>
        public PageModule CurrentPageModule
        {
            get
            {
                return (PageModule)Session["__CurrentPageModule"];
            }
            set
            {
                Session["__CurrentPageModule"] = value;
            }
        }

        /// <summary>
        /// Called before the action method is invoked.
        /// </summary>
        /// <param name="filterContext">Information about the current request and action.</param>
        [HttpGet]
        [HandleErrorWithELMAH]
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            # region Set Referring Page
            //Get the current page
            string[] currentRoute = ControllerContext.HttpContext.Request.RawUrl.ToString().Split('/');
            var currentpage = PageService.GetPage(currentRoute[currentRoute.Count() - 1]);
            // don't mistake the route for a module
            if (currentpage != null)
            {
                CurrentPage = currentpage;
            }
            #endregion

            #region Set referring page
            //get's the referring page
            if (ControllerContext.HttpContext.Request.UrlReferrer != null)
            {
                var referringRoute = ControllerContext.HttpContext.Request.UrlReferrer.ToString().Split('/');
                var referringPage = PageService.GetPage(referringRoute[referringRoute.Count() - 1].TrimStart('/'));

                if (referringPage != null)
                {
                    //dont confuse with current page
                    if (referringPage != CurrentPage)
                    {
                        ReferringPage = referringPage;
                    }
                }
            }
            #endregion

            # region Set current PageModule
            //STILL NEED TO FIGURE OUT WHICH PAGE MODULE I AM IN
            
            //PageModule currentPageModule = PageService.GetPageModule(
            //        PluginService.GetModule(filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
            //                                filterContext.ActionDescriptor.ActionName), CurrentPage);
            ////Dont confuse with post action
            //if (filterContext.RequestContext.HttpContext.Request.RequestType.ToUpper() == "GET")
            //    CurrentPageModule = currentPageModule;
                
            #endregion

            base.OnActionExecuting(filterContext);
        }

        public class HandleErrorWithELMAHAttribute : HandleErrorAttribute
        {
            public override void OnException(ExceptionContext context)
            {
                base.OnException(context);

                var e = context.Exception;
                if (!context.ExceptionHandled   // if unhandled, will be logged anyhow
                        || RaiseErrorSignal(e)      // prefer signaling, if possible
                        || IsFiltered(context))     // filtered?
                    return;

                LogException(e);
            }

            private static bool RaiseErrorSignal(Exception e)
            {
                var context = System.Web.HttpContext.Current;
                if (context == null)
                    return false;
                var signal = ErrorSignal.FromContext(context);
                if (signal == null)
                    return false;
                signal.Raise(e, context);
                return true;
            }

            private static bool IsFiltered(ExceptionContext context)
            {
                var config = context.HttpContext.GetSection("elmah/errorFilter")
                                         as ErrorFilterConfiguration;

                if (config == null)
                    return false;

                var testContext = new ErrorFilterModule.AssertionHelperContext(
                                                                    context.Exception, System.Web.HttpContext.Current);

                return config.Assertion.Test(testContext);
            }

            private static void LogException(Exception e)
            {
                var context = System.Web.HttpContext.Current;
                ErrorLog.GetDefault(context).Log(new Error(e, context));
            }
        }
    }
}
